package com.webex.ta.hydra.gui.component;

import com.webex.ta.hydra.util.HydraUtils;
import com.sun.java.swing.plaf.windows.WindowsTabbedPaneUI;
import com.incors.plaf.alloy.AlloyTabbedPaneUI;

import javax.swing.*;
import javax.swing.text.View;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import javax.swing.plaf.metal.MetalTabbedPaneUI;
import java.awt.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;

/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-9-19
 * Time: 9:30:11
 */
public class ClosableTabbedPaneUI extends AlloyTabbedPaneUI {
    private static final Icon CLOSE_ICON = HydraUtils.getImage("closeUnhovered.png");
    private static final Icon CLOSED_HOVER_ICON = HydraUtils.getImage("closeHovered.png");

    private int hoverButtonIndex = -1;
    @Override
    public void installUI(JComponent c) {
        if (!(c instanceof ClosableTabbedPane))
            throw new IllegalArgumentException("ClosableTabbedPaneUI can only be applied to ClosableTabbedPane");
        super.installUI(c);
    }

    @Override
    protected LayoutManager createLayoutManager() {
        return new TabbedPaneLayout();
    }

    @Override
    protected void installListeners() {
        super.installListeners();
        MouseHandler mh = new MouseHandler();
        tabPane.addMouseMotionListener(mh);
//        tabPane.addMouseListener(mh);
    }

    @Override
    protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
        int width = super.calculateTabWidth(tabPlacement, tabIndex, metrics);
//        ((ClosableTabbedPane)tabPane).
        width = width + 4 + CLOSE_ICON.getIconWidth();
        return width;
    }

    @Override
    protected MouseListener createMouseListener() {
        return new MouseHandler();
    }

    @Override
    public void paint(Graphics g, JComponent c) {
//        g.setColor(Color.black);
//        g.fillRect(0,0,c.getWidth(),c.getHeight());
        super.paint(g, c);
    }

    @Override
    protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, Rectangle iconRect, Rectangle textRect) {
        super.paintTab(g, tabPlacement, rects, tabIndex, iconRect, textRect);
        Rectangle tabRect = rects[tabIndex];
        if (tabIndex == hoverButtonIndex)
            CLOSED_HOVER_ICON.paintIcon(tabPane, g, tabRect.x + tabRect.width - CLOSE_ICON.getIconWidth() - 4, tabRect.y + 1 + (tabRect.height - CLOSE_ICON.getIconHeight()) / 2);
        else
            CLOSE_ICON.paintIcon(tabPane, g, tabRect.x + tabRect.width - CLOSE_ICON.getIconWidth() - 4, tabRect.y + 1 + (tabRect.height - CLOSE_ICON.getIconHeight()) / 2);
    }


    @Override
    protected void layoutLabel(int tabPlacement, FontMetrics metrics, int tabIndex, String title, Icon icon, Rectangle tabRect, Rectangle iconRect, Rectangle textRect, boolean isSelected) {
        textRect.x = textRect.y = iconRect.x = iconRect.y = 0;

        View v = getTextViewForTab(tabIndex);
        if (v != null) {
            tabPane.putClientProperty("html", v);
        }

        SwingUtilities.layoutCompoundLabel((JComponent) tabPane,
                metrics, title, icon,
                SwingUtilities.CENTER,
                SwingUtilities.LEFT,
                SwingUtilities.CENTER,
                SwingUtilities.TRAILING,
                tabRect,
                iconRect,
                textRect,
                textIconGap);

        tabPane.putClientProperty("html", null);

        int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
        int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
        iconRect.x += xNudge;
        iconRect.y += yNudge;
        textRect.x += xNudge;
        textRect.y += yNudge;
    }

    @Override
    protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) {
        int nudge = 0;
        switch (tabPlacement) {
            case LEFT:
                nudge = isSelected ? -1 : 1;
                break;
            case RIGHT:
                nudge = isSelected ? 1 : -1;
                break;
            case BOTTOM:
            case TOP:
            default:
                nudge = 6;
        }
        return nudge;
    }

    private void setRolloverTab(int x, int y) {
        // NOTE:
        // This calls in with false otherwise it could trigger a validate,
        // which should NOT happen if the user is only dragging the
        // mouse around.
        setRolloverTab(tabForCoordinate(tabPane, x, y));
    }


    public class ClosableTabbedPanelLayout extends TabbedPaneLayout {

    }

    private class MouseHandler extends MouseAdapter {

        public void mouseEntered(MouseEvent e) {
            setRolloverTab(e.getX(), e.getY());
        }

        public void mouseExited(MouseEvent e) {
            setRolloverTab(-1);
            tabPane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }

        public void mousePressed(MouseEvent e) {
            if (!tabPane.isEnabled()) {
                return;
            }
            int x = e.getX();
            int y = e.getY();
            int tabIndex = tabForCoordinate(tabPane, x, y);


            if (tabIndex >= 0) {
                Rectangle rect = rects[tabIndex];
                if ((x <= rect.x + rect.width) && (x >= rect.x + rect.width - CLOSE_ICON.getIconWidth() - 4) &&
                        (y >= rect.y && y <= rect.y + rect.height)) {
                    // press on a close icon
                    ((ClosableTabbedPane)tabPane).fireClosingEvent(tabIndex);
                    return;
                }
            }

            if (tabIndex >= 0 && tabPane.isEnabledAt(tabIndex)) {
                if (tabIndex != tabPane.getSelectedIndex()) {
                    // Clicking on unselected tab, change selection, do NOT
                    // request focus.
                    // This will trigger the focusIndex to change by way
                    // of stateChanged.
                    tabPane.setSelectedIndex(tabIndex);
                } else if (tabPane.isRequestFocusEnabled()) {
                    // Clicking on selected tab, try and give the tabbedpane
                    // focus.  Repaint will occur in focusGained.
                    tabPane.requestFocus();
                }
            }
        }

        //
        // MouseMotionListener
        //
        public void mouseDragged(MouseEvent e) {
            setCurorFor(e.getX(), e.getY());
        }

        public void mouseMoved(MouseEvent e) {
            setCurorFor(e.getX(), e.getY());
        }

        private void setCurorFor(int x, int y) {
            int rolloverIdx = tabForCoordinate(tabPane, x, y);
            if (rolloverIdx >= 0) {
                Rectangle rect = rects[rolloverIdx];
                if ((x <= rect.x + rect.width) && (x >= rect.x + rect.width - CLOSE_ICON.getIconWidth() - 4) &&
                        (y >= rect.y && y <= rect.y + rect.height)) {
                    tabPane.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                    setHoverButtonIndex(rolloverIdx);
                } else {
                    tabPane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    setHoverButtonIndex(-1);
                }
            } else {       
                tabPane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                setHoverButtonIndex(-1);
            }
        }
    }

    private void setHoverButtonIndex(int index) {
        if (hoverButtonIndex != index) {
            hoverButtonIndex = index;
            tabPane.repaint();
        }
    }
}
